home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / COMMON.ZIP / XMEM.ALL < prev    next >
Encoding:
Text File  |  1995-10-13  |  31.9 KB  |  1,122 lines

  1. This file contains 3 files:
  2. xmem.h   : c include file
  3. xmem.asm : low level basic XMS acess
  4. xmemc.c  : super easy C access via functions like fopen, fread, fwrite
  5.            xopen, xread, xwrite, xseek etc...
  6.  
  7. FOR DOS REAL mode programs, requires HIMEM.SYS to be loaded in
  8. config.sys.
  9.  
  10. XMEM.H ------------- START --------------------------------------------------
  11. #if !defined(_XMEM_H)
  12. #define _XMEM_H
  13.  
  14. typedef struct xms_node
  15.    {
  16.    long start, size, off;
  17.    short used;
  18.    struct xms_node *next;
  19.    }
  20. xms_node_t;
  21.  
  22. typedef struct
  23.    {
  24.    int handle;
  25.    unsigned long total;
  26.    unsigned long avail;
  27.    unsigned long next_off;
  28.    xms_node_t *next;
  29.    }
  30. xms_head_t;
  31.  
  32. #define XMSBLOCK 16384u
  33. #define XMSBLOCKSHIFT 14
  34.  
  35. extern void LSHL( unsigned long far *SHLnumber, unsigned short n );
  36.  
  37. extern unsigned short XMS_available( void );
  38.  
  39. extern unsigned short XMSblk_available( void );
  40.  
  41. extern short XMS_alloc(unsigned short rsrvd,
  42.                        unsigned short far *size
  43.                       );
  44. extern short XMS_dealloc(unsigned short Hdl );
  45. extern short XMStoMem(unsigned short Handle,   // XMS handle returned by XMS_alloc()
  46.                       unsigned short blk,      // which 16k block to copy to
  47.                       unsigned short blkAdr,   // offset within 16k block
  48.                       unsigned short Bytes,    // bytes to copy
  49.                       void   far *memAdr
  50.                      );
  51. extern short MemToXMS(unsigned short Handle,
  52.                       unsigned short blk,
  53.                       unsigned short blkAdr,
  54.                       unsigned short Bytes,
  55.                       void   far *memAdr
  56.                      );
  57.  
  58. // call these for ease
  59. short alloc_xms(unsigned short far *size);  // size in 16k blocks
  60. // NOTE size is changed to the amount block size was altered by!
  61. // normaly this is zero
  62.  
  63. short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n);
  64. short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n);
  65. void deinit_xms(void);
  66. short init_xms(unsigned short min_blocks);
  67. void qfree_xms(xms_node_t *node);
  68. xms_node_t *qalloc_xms(unsigned long size);
  69. xms_node_t *xms_open(char *file);
  70. short xms_read(void far *buffer, unsigned short n, xms_node_t *node);
  71. short xms_write(void far *buffer, unsigned short n, xms_node_t *node);
  72. long xms_tell(xms_node_t *node);
  73. short xms_seek(xms_node_t *node, long off, short whence);
  74. void xms_close(xms_node_t *node);
  75.  
  76. extern xms_head_t xms_head;
  77.  
  78. #endif
  79. /* ---------------------------------- end of file --------------------- */
  80.  
  81. XMEM.H ------------- END --------------------------------------------------
  82.  
  83. xmem.asm --------------------- START --------------------------------------
  84. ;-----------------------------------------------------------------------
  85. ;
  86. .MODEL MEDIUM
  87.  
  88.         EXTmemError     EQU     7
  89.         XMSmemError     EQU     8
  90.  
  91.  
  92.         ShortAdr        EQU     0
  93.         LongAdr         EQU     1
  94.  
  95. procname        MACRO  Pnam
  96.         PUBLIC  _&Pnam&
  97. _&Pnam&  PROC    FAR
  98. ENDM
  99.  
  100. endproc         MACRO  Pnam
  101.  
  102. _&Pnam&  ENDP
  103.  
  104. ENDM
  105.  
  106. pwrlolvl_TEXT   SEGMENT WORD PUBLIC 'CODE'
  107.  
  108.         ASSUME  CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT
  109.  
  110. SUBTTL  (Local Procedure) XMS_setup - find a XMS driver.
  111. PAGE+
  112.  
  113.                 EVEN
  114. XMSwordByte     LABEL BYTE
  115. XMSword         DW      0
  116.  
  117. XMSmoveSTRUC    STRUC
  118.  
  119. Length          DW      0
  120. LengthX         DW      0
  121. SrcHandle       DW      0
  122. SrcOffset       DW      0
  123. SrcOffsetX      DW      0
  124. DestHandle      DW      0
  125. DestOffset      DW      0
  126. DestOffsetX     DW      0
  127.  
  128. XMSmoveSTRUC    ENDS
  129.  
  130. XMSmainGET      XMSmoveSTRUC  <>
  131. XMSmainPUT      XMSmoveSTRUC  <>
  132. XMSwordGET      XMSmoveSTRUC  <2,,,,,,OFFSET XMSword>
  133. XMSwordPUT      XMSmoveSTRUC  <2,,,OFFSET XMSword>
  134.  
  135. XMSfunctAdr     DW      0, 0
  136.  
  137. ; Don't try to call this from your programs
  138.  
  139. XMS_setup               PROC NEAR
  140.  
  141.         PUSH    DS
  142.         PUSH    ES
  143.         PUSH    BX
  144.  
  145.         MOV     AX,CS                   ; Set Data segment to the code segment.
  146.         MOV     DS,AX                   ;
  147.         MOV     [XMSwordGET.DestOffsetX],AX  ; Set up the move data structures.
  148.         MOV     [XMSwordPUT.SrcOffsetX],AX   ;
  149.  
  150.         MOV     AX,4300H                ; See if a XMS Driver Exists.
  151.         INT     2FH                     ;
  152.         CMP     AL,80H                  ;
  153.         MOV     AX,0                    ;
  154.         JNE     XMS_setup01             ; Return 0 if not.
  155.  
  156.         MOV     AX,4310H                ; If so, set the driver's function
  157.         INT     2FH                     ;  address.
  158.         MOV     [XMSfunctAdr],BX        ;
  159.         MOV     [XMSfunctAdr+2],ES      ;
  160.  
  161.         MOV     AX,1                    ; Return 1.
  162.  
  163.   XMS_setup01:
  164.         POP     BX
  165.         POP     ES
  166.         POP     DS
  167.  
  168.         RET
  169.  
  170. XMS_setup               ENDP
  171.  
  172. SUBTTL  LSHL - Shift an unsigned long left
  173. PAGE+
  174.  
  175.  ;****************************************************************************
  176.  ;* 
  177.  ;* Shift an unsigned long integer left n number of bits.
  178.  ;*
  179.  ;****************************************************************************
  180.  
  181.  ;
  182.  ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n );
  183.  ;
  184.  
  185. LSHLparms STRUC
  186.  
  187.         DW      0, 0
  188.         DW      0
  189. SHLadr   DD      ?
  190. SHLn     DW      ?
  191.  
  192. LSHLparms ENDS
  193.  
  194. procname  LSHL
  195.  
  196.         PUSH    BP
  197.         MOV     BP,SP
  198.  
  199.         PUSH    BX
  200.         PUSH    CX
  201.         PUSH    DX
  202.  
  203.         PUSH    DS
  204.         LDS     BX,SHLadr[BP]
  205.         MOV     CX,SHLn[BP]
  206.  
  207.         MOV     AX,[BX]                 ; Get the long integer.
  208.         MOV     DX,[BX+2]               ; 
  209.  
  210.  LSHL_01:
  211.         SHL     AX,1                    ; Do the long shift.
  212.         RCL     DX,1                    ; 
  213.         LOOP    LSHL_01                 ; 
  214.  
  215.         MOV     [BX],AX                 ; Replace the addressed number.
  216.         MOV     [BX+2],DX               ; 
  217.  
  218.         POP     DS
  219.         POP     DX
  220.         POP     CX
  221.         POP     BX
  222.  
  223.         POP     BP
  224.         RET                             ; Exit
  225.  
  226. endproc   LSHL
  227.  
  228.  
  229. SUBTTL  Extended Memory - Stack template for EXTget, EXTput
  230. PAGE+
  231.  
  232. EXTgpparms STRUC
  233.  
  234.         DW      0, 0
  235.         DW      0
  236. extgpBase    DW      ?
  237. extgpblk     DW      ?
  238. extgpblkAdr  DW      ?
  239. extgpBytes   DW      ?
  240. extgpmemAdr  DW      ?
  241.              DW      ?
  242.  
  243. EXTgpparms ENDS
  244.  
  245.  
  246.  
  247. SUBTTL  Extended Memory - XMS - Return total XMS memory.
  248. PAGE+
  249.  
  250.  ; Use this function to detect wether or not XMS driver installed
  251.  ;
  252.  ; Stack frame definition for unsigned XMS_available( void );
  253.  ;
  254.  ;  The total XMS memory available (in 16k blocks) is returned.
  255.  ;
  256. procname  XMS_available
  257.  
  258.         PUSH    BX
  259.         PUSH    CX
  260.         PUSH    DX
  261.  
  262.         CALL    XMS_setup               ; Ensure XMS memory is set.
  263.         TEST    AX,AX                   ;
  264.         JZ      XMS_available01         ; Return zero if not.
  265.  
  266.         MOV     AH,08H                  ; Set the size function code.
  267.         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
  268.         TEST    AX,AX                   ;
  269.         JZ      XMS_available01         ;
  270.  
  271.         MOV     AX,DX                   ; Set available Kbytes.
  272.         SUB     AX,64                   ; Subtract out the HMA (HIMEM.SYS bug).
  273.         JNC     XMS_available01         ;
  274.         XOR     AX,AX                   ; Set zero if underflow.
  275.  
  276.   XMS_available01:
  277.         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
  278.         SHR     AX,CL                   ;
  279.  
  280.         POP     DX
  281.         POP     CX
  282.         POP     BX
  283.  
  284.         RET                             ; Exit
  285.  
  286. endproc   XMS_available
  287.  
  288. SUBTTL  Extended Memory - XMS - Return largest block XMS mem.
  289. PAGE+
  290.  
  291.  ;
  292.  ; Stack frame definition for unsigned XMSblk_available( void );
  293.  ;
  294.  ;  The size of the largest block of XMS memory available,
  295.  ;  (in 16Kbyte blocks) is returned.
  296.  ;
  297. procname  XMSblk_available
  298.  
  299.         PUSH    BX
  300.         PUSH    CX
  301.         PUSH    DX
  302.  
  303.         CALL    XMS_setup               ; Ensure XMS memory is set.
  304.         TEST    AX,AX                   ;
  305.         JZ      XMSblk_available01      ; Return zero if not.
  306.  
  307.         MOV     AH,08H                  ; Set the size function code.
  308.         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
  309.         TEST    AX,AX                   ;
  310.         JZ      XMSblk_available01      ;
  311.  
  312.         SUB     DX,64                   ; Subtract out the HMA (HIMEM.SYS bug).
  313.         JNC     XMSblk_available0X      ;
  314.         XOR     DX,DX                   ; Set zero if underflow.
  315.  
  316.  XMSblk_available0X:
  317.         CMP     AX,DX                   ;
  318.         JBE     XMSblk_available01      ;
  319.         MOV     AX,DX                   ; Set available Kbytes.
  320.  
  321.   XMSblk_available01:
  322.         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
  323.         SHR     AX,CL                   ;
  324.  
  325.         POP     DX
  326.         POP     CX
  327.         POP     BX
  328.  
  329.         RET                             ; Exit
  330.  
  331. endproc   XMSblk_available
  332.  
  333. SUBTTL  Extended Memory - XMS De-allocate a memory block.
  334. PAGE+
  335.  
  336.  ;
  337.  ; Stack frame definition for int XMS_dealloc( int Hdl );
  338.  ;
  339.  ; Zero is returned if the operation fails, non-zero if success.
  340.  ;
  341.  ; its really important to do this, only other way to recover
  342.  ; XMS blocks is to re-boot
  343.  
  344. XMSdealparms STRUC
  345.  
  346.         DW      0, 0
  347.         DW      0
  348. xmsdealHdl  DW      ?
  349.  
  350. XMSdealparms ENDS
  351.  
  352.  
  353. procname  XMS_dealloc
  354.  
  355.         PUSH    BP
  356.         MOV     BP,SP
  357.  
  358.         PUSH    BX
  359.         PUSH    DX
  360.  
  361. ;        CALL    XMS_setup               ; Ensure XMS memory is set.
  362. ;        TEST    AX,AX                   ;
  363. ;        JZ      XMS_dealloc01           ; Return zero if not.
  364.  
  365.         MOV     DX,xmsdealHdl[BP]       ; Get the handle to de-allocate.
  366.         MOV     AH,0AH                  ;
  367.  
  368.         CALL    DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.
  369.  
  370.   XMS_dealloc01:
  371.         POP     DX
  372.         POP     BX
  373.  
  374.         POP     BP
  375.         RET                             ; Exit
  376.  
  377. endproc   XMS_dealloc
  378.  
  379. SUBTTL  Extended Memory - XMS Allocate a memory block.
  380. PAGE+
  381.  
  382.  ;
  383.  ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );
  384.  ;
  385.  ;     rsrved and size are in 16K byte blocks.
  386.  ;     rsrved is mem set aside for EMS, generaly zero
  387.  ;
  388.  ;  Zero is returned if the operation fails.
  389.  ;  Block (XMS) handle is returned if success.
  390.  ;
  391.  ;  size - is reduced by the amount of XMS memory actually allocated.
  392.  ;
  393.  
  394. XMSalparms STRUC
  395.  
  396.         DW      0, 0
  397.         DW      0
  398. xmsalrsrvd DW      ?
  399. xmsalsize  DD      ?
  400.  
  401. XMSalparms ENDS
  402.  
  403. procname  XMS_alloc
  404.  
  405.         PUSH    BP
  406.         MOV     BP,SP
  407.  
  408.         PUSH    BX
  409.         PUSH    CX
  410.         PUSH    DX
  411.         PUSH    DI
  412.         PUSH    ES
  413.         PUSH    DS
  414.  
  415.         MOV     AX,CS                   ; Set the data segment to the code
  416.         MOV     DS,AX                   ;  segment.
  417.  
  418.         MOV     CX,4                    ;
  419.         ADD     xmsalrsrvd[BP],CX       ; Subtract out the HMA (HIMEM.SYS bug).
  420.         SHL     xmsalrsrvd[BP],CL       ; Convert reserved blocks to K-bytes.
  421.  
  422.         LES     DI,xmsalsize[BP]        ; Load size address.
  423.         XOR     AX,AX                   ;
  424.         MOV     BX,ES:[DI]              ; Get the requested size in blocks.
  425.  
  426.         TEST    BX,0F000H               ; Check for more than 64 Megabytes.
  427.         JZ      XMS_alloc01             ;
  428.         MOV     BX,00FFFH               ;
  429.  
  430.   XMS_alloc01:
  431.         MOV     CL,4                    ;
  432.         SHL     BX,CL                   ; Convert to K-Bytes.
  433.         MOV     CX,BX                   ; In CX.
  434.         JZ      XMS_alloc05             ; Return zero if no size requested.
  435.  
  436. ;        CALL    XMS_setup               ; Ensure XMS memory is set.
  437. ;        TEST    AX,AX                   ;
  438. ;        JZ      XMS_alloc05             ; Return zero if not.
  439.  
  440.         XOR     BX,BX                   ;
  441.         MOV     AH,08H                  ; Set to Query Free XMS Memory.
  442.         CALL    DWORD PTR [XMSfunctAdr] ;
  443.  
  444.         SUB     DX,xmsalrsrvd[BP]       ; Subtract out reserved blocks.
  445.         JB      XMS_alloc03             ; Ensure no borrow.
  446.         CMP     AX,DX                   ;
  447.         JBE     XMS_alloc02             ;
  448.         MOV     AX,DX                   ;
  449.  
  450.   XMS_alloc02:
  451.         MOV     DX,AX                   ;
  452.         CMP     AX,68                   ; Ensure enough memory to allocate.
  453.  
  454.   XMS_alloc03:
  455.         MOV     AX,0                    ;
  456.         JB      XMS_alloc05             ; Exit if not.
  457.  
  458.         CMP     BL,80H                  ; Check for errors.
  459.         JE      XMS_alloc05             ;
  460.         CMP     BL,81H                  ;
  461.         JE      XMS_alloc05             ;
  462.  
  463.         CMP     CX,DX                   ; Check actual against requested size.
  464.         JBE     XMS_alloc04             ;
  465.         MOV     CX,DX                   ; Set if actual < requested.
  466.  
  467.   XMS_alloc04:
  468.         MOV     DX,CX                   ; Set requested size.
  469.         MOV     AH,09H                  ;
  470.         CALL    DWORD PTR [XMSfunctAdr] ; Allocate it.
  471.         DEC     AX                      ; Check for errors.
  472.         MOV     AX,0                    ;
  473.         JNZ     XMS_alloc05             ;
  474.  
  475.  
  476.         MOV     AX,CX                   ; Convert allocated size in KBytes
  477.         MOV     CL,4                    ; to allocated blocks.
  478.         SHR     AX,CL                   ;
  479.  
  480.         SUB     ES:[DI],AX              ; Subtract the blocks allocated.
  481.         MOV     AX,DX                   ; Set to return the handle.
  482.  
  483.   XMS_alloc05:
  484.         POP     DS
  485.         POP     ES
  486.         POP     DI
  487.         POP     DX
  488.         POP     CX
  489.         POP     BX
  490.  
  491.         POP     BP
  492.         RET                             ; Exit
  493.  
  494. endproc  XMS_alloc
  495.  
  496. SUBTTL  Extended Memory - XMS get, put Stack Frame definition
  497. PAGE+
  498.  
  499.  
  500. XMSgpparms STRUC
  501.  
  502.         DW      0, 0
  503.         DW      0
  504. xmsgpHdl     DW      ?
  505. xmsgpblk     DW      ?
  506. xmsgpblkAdr  DW      ?
  507. xmsgpBytes   DW      ?
  508. xmsgpmemAdr  DD      ?
  509.  
  510. XMSgpparms ENDS
  511.  
  512. SUBTTL  Extended Memory - XMStoMem
  513. PAGE+
  514.  
  515.  
  516.  ;
  517.  ; Stack frame definition for int XMStoMem( unsigned Handle,
  518.  ;                                          unsigned blk,
  519.  ;                                          unsigned blkAdr,
  520.  ;                                          unsigned Bytes,
  521.  ;                                          char     *memAdr
  522.  ;                                        );
  523.  ;
  524.  ;  XMSmemError is returned if the operation fails, Zero if success.
  525.  ;
  526.  
  527. procname  XMStoMem
  528.  
  529.         PUSH    BP
  530.         MOV     BP,SP
  531.  
  532.         PUSH    BX
  533.         PUSH    CX
  534.         PUSH    DX
  535.         PUSH    SI
  536.         PUSH    DI
  537.         PUSH    ES
  538.         PUSH    DS
  539.  
  540.         MOV     AX,CS                   ; Set Data Segment to Code Segment.
  541.         MOV     DS,AX                   ;
  542.  
  543.         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
  544.         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
  545.         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
  546.         MOV     [XMSmainGET.SrcHandle],DX ; Set it in the move structures.
  547.         MOV     [XMSwordGET.SrcHandle],DX ;
  548.  
  549.         XOR     DX,DX                   ;
  550.         MOV     DI,xmsgpblk[BP]         ; Get the block number.
  551.         SHR     DI,1                    ; Form the 32 bit XMS address in
  552.         RCR     DX,1                    ;  DI:DX.
  553.         SHR     DI,1                    ;
  554.         RCR     DX,1                    ;
  555.         ADD     DX,xmsgpblkAdr[BP]      ;
  556.  
  557.         TEST    CX,1                    ; Check for an odd number of bytes
  558.         JZ      XMStoMem02              ;  to transfer.
  559.  
  560.         DEC     CX                      ; Decrement to an even number of bytes.
  561.  
  562.         TEST    DX,1                    ; Check for an odd XMS address.
  563.         JZ      XMStoMem01              ;
  564.  
  565.                                         ; XMS address is odd.
  566.                                         ; -------------------
  567.         DEC     DX                      ;
  568.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  569.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  570.  
  571.         MOV     AH,0BH                  ; Set the XMS move, function code.
  572.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  573.  
  574.         PUSH    BX                      ;
  575.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  576.         POP     BX                      ;
  577.         DEC     AX                      ; Check for errors.
  578.         JNZ     XMStoMem03              ; Error out if error.
  579.  
  580.         MOV     AX,[XMSword]            ; Get the moved word.
  581.  
  582.         MOV     ES:[BX],AH              ; Move the odd byte to memory.
  583.  
  584.         INC     BX                      ; Reset the memory address.
  585.         ADD     DX,2                    ; And the XMS address.
  586.  
  587.         JMP     XMStoMem02              ; Move the block.
  588.  
  589.  
  590.   XMStoMem01:
  591.                                         ; XMS address is even.
  592.                                         ; --------------------
  593.         ADD     DX,CX                   ;
  594.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  595.         SUB     DX,CX                       ;
  596.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  597.  
  598.         MOV     AH,0BH                  ; Set the XMS move, function code.
  599.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  600.  
  601.         PUSH    BX                      ;
  602.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  603.         POP     BX                      ;
  604.         DEC     AX                      ; Check for errors.
  605.         JNZ     XMStoMem03              ; Error out if error.
  606.  
  607.         MOV     AX,[XMSword]            ; Get the moved word.
  608.  
  609.         XCHG    DI,CX                   ;
  610.         MOV     ES:[BX+DI],AL           ; Move the odd byte to memory.
  611.         XCHG    DI,CX                   ;
  612.  
  613.   XMStoMem02:
  614.         JCXZ    XMStoMem04              ; Avoid a zero byte move.
  615.  
  616.         MOV     XMSmainGET.Length,CX    ; Set length for the move.
  617.  
  618.         MOV     XMSmainGET.DestOffset,BX   ; Set Memory address.
  619.         MOV     XMSmainGET.DestOffsetX,ES  ;
  620.  
  621.         MOV     XMSmainGET.SrcOffset,DX    ; Set XMS address.
  622.         MOV     XMSmainGET.SrcOffsetX,DI   ;
  623.  
  624.         MOV     AH,0BH                  ; Set the XMS move, function code.
  625.         MOV     SI,OFFSET XMSmainGET    ; Set address of the move structure.
  626.  
  627.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  628.         DEC     AX                      ; Check for errors.
  629.         JZ      XMStoMem05
  630.  
  631.   XMStoMem03:
  632.         MOV     AX,XMSmemError          ; Set error code if error.
  633.         JMP     XMStoMem05              ;
  634.  
  635.   XMStoMem04:
  636.         XOR     AX,AX                   ;
  637.  
  638.   XMStoMem05:
  639.         POP     DS
  640.         POP     ES
  641.         POP     DI
  642.         POP     SI
  643.         POP     DX
  644.         POP     CX
  645.         POP     BX
  646.  
  647.         POP     BP
  648.         RET                             ; Exit
  649.  
  650. endproc  XMStoMem
  651.  
  652. SUBTTL  Extended Memory - MemToXMS
  653. PAGE+
  654.  
  655.  
  656.  ;
  657.  ; Stack frame definition for int MemToXMS( unsigned Handle,
  658.  ;                                        unsigned blk,
  659.  ;                                        unsigned blkAdr,
  660.  ;                                        unsigned Bytes,
  661.  ;                                        char     *memAdr
  662.  ;                                       );
  663.  ;
  664.  ;  XMSmemError is returned if the operation fails, Zero if success.
  665.  ;
  666.  
  667. procname  MemToXMS
  668.  
  669.         PUSH    BP
  670.         MOV     BP,SP
  671.  
  672.         PUSH    BX
  673.         PUSH    CX
  674.         PUSH    DX
  675.         PUSH    SI
  676.         PUSH    DI
  677.         PUSH    ES
  678.         PUSH    DS
  679.  
  680.         MOV     AX,CS                   ;
  681.         MOV     DS,AX                   ;
  682.  
  683.         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
  684.         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
  685.         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
  686.         MOV     [XMSmainPUT.DestHandle],DX ; Set it in the move structures.
  687.         MOV     [XMSwordPUT.DestHandle],DX ;
  688.         MOV     [XMSwordGET.SrcHandle],DX  ;
  689.  
  690.         XOR     DX,DX                   ;
  691.         MOV     DI,xmsgpblk[BP]         ; Get the block number.
  692.         SHR     DI,1                    ; Form the 32 bit XMS address in
  693.         RCR     DX,1                    ;  DI:DX.
  694.         SHR     DI,1                    ;
  695.         RCR     DX,1                    ;
  696.         ADD     DX,xmsgpblkAdr[BP]      ;
  697.  
  698.         TEST    CX,1                    ; Check for an odd number of bytes
  699.         JZ      MemToXMS02              ;  to transfer.
  700.  
  701.         DEC     CX                      ; Decrement to an even number of bytes.
  702.  
  703.         TEST    DX,1                    ; Check for an odd XMS address.
  704.         JZ      MemToXMS01              ;
  705.  
  706.                                         ; XMS address is odd.
  707.                                         ; -------------------
  708.         DEC     DX                      ;
  709.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  710.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  711.         MOV     [XMSwordPUT.DestOffset],DX  ;
  712.         MOV     [XMSwordPUT.DestOffsetX],DI ;
  713.  
  714.         MOV     AH,0BH                  ; Set the XMS move, function code.
  715.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  716.  
  717.         PUSH    BX                      ;
  718.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  719.         POP     BX                      ;
  720.         DEC     AX                      ; Check for errors.
  721.         JNZ     MemToXMS03              ; Error out if error.
  722.  
  723.         MOV     AH,ES:[BX]              ; Get the odd memory byte.
  724.  
  725.         MOV     [XMSwordByte+1],AH      ; Put it in the moved word.
  726.  
  727.         MOV     AH,0BH                  ; Set the XMS move, function code.
  728.         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
  729.  
  730.         PUSH    BX                      ;
  731.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  732.         POP     BX                      ;
  733.         DEC     AX                      ; Check for errors.
  734.         JNZ     MemToXMS03              ; Error out if error.
  735.  
  736.         INC     BX                      ; Reset the memory address.
  737.         ADD     DX,2                    ; And the XMS address.
  738.  
  739.         JMP     MemToXMS02              ; Move the block.
  740.  
  741.   MemToXMS01:
  742.                                         ; XMS address is even.
  743.                                         ; --------------------
  744.         ADD     DX,CX                   ;
  745.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  746.         MOV     [XMSwordPUT.DestOffset],DX  ;
  747.         SUB     DX,CX                       ;
  748.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  749.         MOV     [XMSwordPUT.DestOffsetX],DI ;
  750.  
  751.         MOV     AH,0BH                  ; Set the XMS move, function code.
  752.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  753.  
  754.         PUSH    BX                      ;
  755.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  756.         POP     BX                      ;
  757.         DEC     AX                      ; Check for errors.
  758.         JNZ     MemToXMS03              ; Error out if error.
  759.  
  760.         XCHG    DI,CX                   ;
  761.         MOV     AL,ES:[BX+DI]           ; Get the odd memory byte.
  762.         XCHG    DI,CX                   ;
  763.  
  764.         MOV     [XMSwordByte],AL        ; Set the moved word.
  765.  
  766.         MOV     AH,0BH                  ; Set the XMS move, function code.
  767.         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
  768.  
  769.         PUSH    BX                      ;
  770.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  771.         POP     BX                      ;
  772.         DEC     AX                      ; Check for errors.
  773.         JNZ     MemToXMS03              ; Error out if error.
  774.  
  775.   MemToXMS02:
  776.         JCXZ    MemToXMS04              ; Avoid a zero byte move.
  777.  
  778.         MOV     XMSmainPUT.Length,CX    ; Set length for the move.
  779.  
  780.         MOV     XMSmainPUT.SrcOffset,BX    ; Set Memory address.
  781.         MOV     XMSmainPUT.SrcOffsetX,ES   ;
  782.  
  783.         MOV     XMSmainPUT.DestOffset,DX   ; Set XMS address.
  784.         MOV     XMSmainPUT.DestOffsetX,DI  ;
  785.  
  786.         MOV     AH,0BH                  ; Set the XMS move, function code.
  787.         MOV     SI,OFFSET XMSmainPUT    ; Set address of the move structure.
  788.  
  789.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  790.         DEC     AX                      ; Check for errors.
  791.         JZ      MemToXMS05
  792.  
  793.   MemToXMS03:
  794.         MOV     AX,XMSmemError          ; Set error code if error.
  795.         JMP     MemToXMS05              ;
  796.  
  797.   MemToXMS04:
  798.         XOR     AX,AX                   ;
  799.  
  800.   MemToXMS05:
  801.         POP     DS
  802.         POP     ES
  803.         POP     DI
  804.         POP     SI
  805.         POP     DX
  806.         POP     CX
  807.         POP     BX
  808.  
  809.         POP     BP
  810.         RET                             ; Exit
  811.  
  812. endproc  MemToXMS
  813.  
  814.  
  815. SUBTTL  Last Page
  816. PAGE+
  817.  
  818. pwrlolvl_TEXT   ENDS
  819.  
  820.         END
  821.  
  822.  
  823. xmem.asm --------------------- END --------------------------------------
  824.  
  825. xmemc.c ---------------------------- START -------------------------
  826.  
  827. /*
  828.  
  829.    Copyright 1994 Alec Russell, ALL rights reserved
  830.         Permission granted to use as you wish.
  831.  
  832.    Slightly higher level xms calls than xmem.asm
  833.  
  834. */
  835.  
  836. #include <stdio.h>
  837. #include <io.h>
  838. #include <string.h>
  839. #include <malloc.h>
  840.  
  841. #include <xmem.h>
  842.  
  843. xms_head_t xms_head={0};  // set handle to zero
  844.  
  845.  
  846. /* ---------------------- alloc_xms() ----------------- February 19,1994 */
  847. short alloc_xms(unsigned short far *size)  // size in 16k blocks
  848. {
  849.    return(XMS_alloc(0, size));
  850. }
  851.  
  852. /* ---------------------- xms_to_mem() ---------------- February 19,1994 */
  853. short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n)
  854. {
  855.    unsigned short block, boff;
  856.  
  857.    block=off >> XMSBLOCKSHIFT;
  858.    boff=off - (block << XMSBLOCKSHIFT);
  859.  
  860.    return(XMStoMem(handle, block, boff, n, p));
  861. }
  862.  
  863. /* ---------------------- mem_to_xms() ---------------- February 19,1994 */
  864. short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n)
  865. {
  866.    unsigned short block, boff;
  867.  
  868.    block=off >> XMSBLOCKSHIFT;
  869.    boff=off - (block << XMSBLOCKSHIFT);
  870.  
  871.    return(MemToXMS(handle, block, boff, n, p));
  872. }
  873.  
  874. /* ---------------------- qalloc_xms() -------------------- March 8,1994 */
  875. xms_node_t *qalloc_xms(unsigned long size)
  876. {
  877.    xms_node_t *node=NULL;
  878.    xms_node_t *t1;
  879.  
  880.    if ( size <= xms_head.avail )
  881.       {
  882.       // look for existing node
  883.       t1=xms_head.next;
  884.       while ( t1 )
  885.          {
  886.          if ( t1->used == 0 && t1->size >= size )
  887.             {
  888.             t1->off=0;
  889.             t1->used=1;
  890.             node=t1;
  891.             break;
  892.             }
  893.          else
  894.             t1=t1->next;
  895.          }
  896.  
  897.       if ( node == NULL ) // didn't find existing node
  898.          {
  899.          node=malloc(sizeof(xms_node_t));
  900.          if ( node )
  901.             {
  902.             node->off=0;
  903.             node->used=1;
  904.             node->size=size;
  905.             node->next=NULL;
  906.             node->start=xms_head.next_off;
  907.             xms_head.avail-=size;
  908.             xms_head.next_off+=size;
  909.             if ( xms_head.next == NULL )
  910.                {
  911.                xms_head.next=node;
  912.                }
  913.             else
  914.                {
  915.                t1=xms_head.next;
  916.                while ( t1->next )
  917.                   t1=t1->next;
  918.                t1->next=node;
  919.                }
  920.             }
  921.          else
  922.             pr2("out of near mem in qalloc_xms");
  923.          }
  924.       }
  925.    else
  926.       pr2("out of xms mem in qalloc size %lu avail %lu", size, xms_head.avail);
  927.  
  928.    return(node);
  929. }
  930.  
  931. /* ---------------------- qfree_xms() --------------------- March 8,1994 */
  932. void qfree_xms(xms_node_t *node)
  933. {
  934.    xms_node_t *t1;
  935.  
  936.    if ( xms_head.next )
  937.       {
  938.       t1=xms_head.next;
  939.       while ( t1 != node && t1 )
  940.          t1=t1->next;
  941.  
  942.       if ( t1 )
  943.          {
  944.          t1->used=0;
  945.          }
  946.       else
  947.          pr2("ERROR didn't find node qfree");
  948.       }
  949.    else
  950.       {
  951.       pr2("ATTEMPTED to qfree empty list");
  952.       }
  953. }
  954.  
  955. /* ---------------------- xms_open() ---------------------- March 8,1994 */
  956. xms_node_t *xms_open(char *file)
  957. {
  958.    int i;
  959.    xms_node_t *node=NULL;
  960.    FILE *fp;
  961.    char *buffer;
  962.    unsigned long off;
  963.  
  964.    fp=fopen(file, "rb");
  965.    if ( fp )
  966.       {
  967.       node=qalloc_xms(filelength(fileno(fp)));
  968.       if ( node )
  969.          {
  970.          buffer=malloc(4096);
  971.          if ( buffer )
  972.             {
  973.             off=0l;
  974.             while ( (i=fread(buffer, 1, 4096, fp)) )
  975.                {
  976.                mem_to_xms(xms_head.handle, (char far *)buffer, off+node->start, i);
  977.                off+=i;
  978.                }
  979.  
  980.             free(buffer);
  981.             }
  982.          else
  983.             pr2("out of mem in xms_open 1");
  984.          }
  985.  
  986.       fclose(fp);
  987.       }
  988.    else
  989.       pr2("ERROR opening %s in xms_open", file);
  990.  
  991.    return(node);
  992. }
  993.  
  994. /* ---------------------- xms_read() ---------------------- March 8,1994 */
  995. short xms_read(void far *buffer, unsigned short n, xms_node_t *node)
  996. {
  997.  
  998.    if ( node->off >= node->size )
  999.       return 0;
  1000.  
  1001.    if ( n+node->off > node->size )
  1002.       n=node->size - node->off;
  1003.  
  1004.    xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);
  1005.    node->off+=n;
  1006.  
  1007.    return(n);
  1008. }
  1009.  
  1010. /* ---------------------- xms_write() ---------------------- March 8,1994 */
  1011. short xms_write(void far *buffer, unsigned short n, xms_node_t *node)
  1012. {
  1013.  
  1014.    if ( node->off >= node->size )
  1015.       return 0;
  1016.  
  1017.    if ( n+node->off > node->size )
  1018.       n=node->size - node->off;
  1019.  
  1020.    mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);
  1021.    node->off+=n;
  1022.  
  1023.    return(n);
  1024. }
  1025.  
  1026.  
  1027. /* ---------------------- xms_tell() ---------------------- March 8,1994 */
  1028. long xms_tell(xms_node_t *node)
  1029. {
  1030.    return node->off;
  1031. }
  1032.  
  1033. /* ---------------------- xms_seek() ---------------------- March 8,1994 */
  1034. short xms_seek(xms_node_t *node, long off, short whence)
  1035. {
  1036.    short err=0;
  1037.  
  1038.    switch ( whence )
  1039.       {
  1040.       case SEEK_SET:
  1041.          if ( off < 0l || off > node->size )
  1042.             err=1;
  1043.          else
  1044.             node->off=off;
  1045.          break;
  1046.  
  1047.       case SEEK_END:
  1048.          if ( off > 0l || (node->size + off) < 0l )
  1049.             err=1;
  1050.          else
  1051.             node->off=node->size + off;
  1052.          break;
  1053.  
  1054.       case SEEK_CUR:
  1055.          if ( node->off + off < 0l || node->off + off > node->size )
  1056.             err=1;
  1057.          else
  1058.             node->off+=off;
  1059.          break;
  1060.       }
  1061.  
  1062.    return(err);
  1063. }
  1064.  
  1065. /* ---------------------- xms_close() --------------------- March 8,1994 */
  1066. void xms_close(xms_node_t *node)
  1067. {
  1068.    qfree_xms(node);
  1069. }
  1070.  
  1071. /* ---------------------- init_xms() ---------------------- March 8,1994 */
  1072. short init_xms(unsigned short min_blocks)
  1073. {
  1074.    unsigned short blocks;
  1075.  
  1076.    blocks=XMSblk_available();
  1077.    if ( blocks >= min_blocks )
  1078.       {
  1079.       memset(&xms_head, 0, sizeof(xms_head_t));
  1080.       if ( (xms_head.handle=alloc_xms(&blocks)) )
  1081.          {
  1082.          pr2("blocks minus by = %u", blocks);
  1083.          min_blocks-=blocks;
  1084.          xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;
  1085.          blocks=min_blocks;
  1086.          }
  1087.       else
  1088.          blocks=0;
  1089.       }
  1090.    else
  1091.       blocks=0;
  1092.  
  1093.    return(blocks);
  1094. }
  1095.  
  1096. /* ---------------------- deinit_xms() -------------------- March 8,1994 */
  1097. void deinit_xms(void)
  1098. {
  1099.    xms_node_t *t1, *t2;
  1100.  
  1101.    if ( xms_head.handle )
  1102.       {
  1103.       XMS_dealloc(xms_head.handle);
  1104.       if ( xms_head.next )
  1105.          {
  1106.          t1=xms_head.next;
  1107.          t2=t1->next;
  1108.          while ( t1 )
  1109.             {
  1110.             free(t1);
  1111.             t1=t2;
  1112.             t2=t1->next;
  1113.             }
  1114.          }
  1115.  
  1116.       memset(&xms_head, 0, sizeof(xms_head_t));
  1117.       }
  1118. }
  1119. /* --------------------------- end of file ------------------------- */
  1120.  
  1121. xmemc.c ---------------------------- END -------------------------
  1122.